package com.example.vpn_demo

import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.content.Intent
import android.content.pm.ServiceInfo
import android.net.VpnService
import android.os.Build
import android.os.ParcelFileDescriptor
import android.util.Log
import android.widget.Toast
import androidx.core.app.NotificationCompat
import com.example.vpn_demo.cert.CertificateManager
import com.example.vpn_demo.packet.Packet
import com.example.vpn_demo.proxy.BrowserMobProxyManager
import com.example.vpn_demo.packet.PacketProcessor
import com.example.vpn_demo.packet.Protocol
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.net.DatagramPacket
import java.net.DatagramSocket
import java.net.InetAddress
import java.net.InetSocketAddress
import java.net.Socket
import java.nio.ByteBuffer

class MyVpnService : VpnService() {
    private var vpnInterface: ParcelFileDescriptor? = null
    private val certificateManager by lazy { CertificateManager(this) }
    private val proxyManager by lazy { BrowserMobProxyManager() }
    private var isRunning = false
    private lateinit var packetProcessor: PacketProcessor

    companion object {
        private const val TAG = "MyVpnService"
        private const val MTU = 1500
    }

    override fun onCreate() {
        super.onCreate()
        startForeground()
    }

    private fun startForeground() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channelId = "vpn_service"
            val channelName = "VPN Service"
            val channel = NotificationChannel(
                channelId,
                channelName,
                NotificationManager.IMPORTANCE_LOW
            ).apply {
                setShowBadge(false)
                enableLights(false)
                enableVibration(false)
            }
            
            val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(channel)

            val notification = NotificationCompat.Builder(this, channelId)
                .setContentTitle("VPN Service")
                .setContentText("Running")
                .setSmallIcon(R.mipmap.ic_launcher)
                .setOngoing(true)
                .setCategory(Notification.CATEGORY_SERVICE)
                .build()

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                startForeground(1, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC)
            } else {
                startForeground(1, notification)
            }
        }
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        CoroutineScope(Dispatchers.Default).launch {
            try {
                // 启动代理服务器
                proxyManager.start(
                    certificateManager.getRootCertificate(),
                    certificateManager.getCertificateFile()
                )

                // 设置 VPN
                vpnInterface = setupVpn(intent?.getStringArrayListExtra("selected_apps"))
                
                // 初始化数据包处理器
                packetProcessor = PacketProcessor(
                    FileInputStream(vpnInterface?.fileDescriptor),
                    FileOutputStream(vpnInterface?.fileDescriptor),
                    BrowserMobProxyManager.PROXY_PORT
                )

                isRunning = true
                startForwardingThread()
            } catch (e: Exception) {
                Log.e(TAG, "VPN 设置失败", e)
                stopSelf()
            }
        }
        return START_NOT_STICKY
    }

    private fun setupVpn(selectedApps: ArrayList<String>?): ParcelFileDescriptor {
        return Builder().apply {
            // 设置 VPN 地址和路由
            addAddress("10.0.0.2", 32)
            addRoute("0.0.0.0", 0)
            
            // 使用系统 DNS
            val systemDns = getSystemDns()
            addDnsServer(systemDns)
            
            // 备用 DNS
            addDnsServer("119.29.29.29")  // 腾讯 DNS
            addDnsServer("223.6.6.6")     // 阿里备用 DNS
            
            // 设置 MTU
            setMtu(1500)
            
            // 允许绕过 VPN 的应用
            selectedApps?.forEach { packageName ->
                try {
                    addAllowedApplication(packageName)
                } catch (e: Exception) {
                    Log.e(TAG, "添加应用失败: $packageName", e)
                }
            }
            
            setSession("VPN Demo")
            setBlocking(true)
            
        }.establish() ?: throw IllegalStateException("无法创建 VPN 接口")
    }

    override fun onDestroy() {
        isRunning = false
        proxyManager.stop()
        vpnInterface?.close()
        super.onDestroy()
    }

    private fun startVpnThread() {
        Thread {
            val vpnInput = FileInputStream(vpnInterface?.fileDescriptor)
            val vpnOutput = FileOutputStream(vpnInterface?.fileDescriptor)
            val buffer = ByteBuffer.allocate(MTU)
            val packet = ByteArray(MTU)
            
            while (isRunning) {
                try {
                    // 从 VPN 接口读取数据
                    val length = vpnInput.read(packet)
                    if (length <= 0) {
                        Thread.sleep(100)
                        continue
                    }

                    buffer.clear()
                    buffer.put(packet, 0, length)
                    buffer.flip()
                    
                    Log.d(TAG, "收到 VPN 数据包: $length bytes")
                    
                    // 将数据写回 VPN 接口
                    vpnOutput.write(packet, 0, length)
                    vpnOutput.flush()

                } catch (e: Exception) {
                    if (isRunning) {
                        Log.e(TAG, "处理 VPN 数据包时出错", e)
                    }
                }
            }

            try {
                vpnInput.close()
                vpnOutput.close()
            } catch (e: Exception) {
                Log.e(TAG, "关闭 VPN 流时出错", e)
            }
        }.start()
    }

    private fun forwardPackets() {
        while (isRunning && !Thread.interrupted()) {
            try {
                val packet = packetProcessor.readPacket()
                if (packet != null) {
                    // 记录数据包信息
                    val packetType = when (packet.protocol) {
                        Protocol.TCP -> {
                            when (packet.destinationPort) {
                                80 -> "HTTP"
                                443 -> "HTTPS"
                                else -> "TCP"
                            }
                        }
                        Protocol.UDP -> {
                            when (packet.destinationPort) {
                                53 -> "DNS"
                                else -> "UDP"
                            }
                        }
                        else -> "Unknown"
                    }

                    Log.i(TAG, """
                        ┌──────────── 数据包信息 ────────────
                        │ 类型: $packetType
                        │ 源地址: ${packet.sourceAddress}:${packet.sourcePort}
                        │ 目标地址: ${packet.destinationAddress}:${packet.destinationPort}
                        │ 数据大小: ${packet.data.size} bytes
                        └────────────────────────────────────
                    """.trimIndent())

                    // 创建到目标服务器的连接并转发数据
                    when (packet.protocol) {
                        Protocol.TCP -> handleTcpPacket(packet)
                        Protocol.UDP -> handleUdpPacket(packet)
                        else -> Log.w(TAG, "不支持的协议类型: ${packet.protocol}")
                    }
                }
            } catch (e: Exception) {
                Log.e(TAG, "处理数据包失败", e)
            }
        }
    }

    private fun handleTcpPacket(packet: Packet) {
        var socket: Socket? = null
        try {
            socket = Socket()
            protect(socket)
            
            // 设置 socket 选项
            socket.apply {
                tcpNoDelay = true
                keepAlive = true
                soTimeout = 10000  // 增加到10秒超时
                receiveBufferSize = 65536
                sendBufferSize = 65536
            }
            
            try {
                val address = InetAddress.getByName(packet.destinationAddress)
                Log.d(TAG, "正在连接: ${address.hostAddress}:${packet.destinationPort}")
                socket.connect(InetSocketAddress(address, packet.destinationPort), 10000)
                
                // 发送数据
                socket.getOutputStream().apply {
                    write(packet.data)
                    flush()
                }

                // 读取响应
                val buffer = ByteArray(65536)  // 增大缓冲区
                val inputStream = socket.getInputStream()
                
                while (true) {
                    val bytesRead = inputStream.read(buffer)
                    if (bytesRead <= 0) break
                    
                    packetProcessor.writePacket(buffer.copyOf(bytesRead))
                    Log.d(TAG, "TCP响应: $bytesRead bytes")
                }
                
            } catch (e: Exception) {
                Log.e(TAG, "TCP连接失败: ${packet.destinationAddress}:${packet.destinationPort}", e)
                throw e
            }
            
        } catch (e: Exception) {
            Log.e(TAG, "TCP包处理失败", e)
        } finally {
            try {
                socket?.close()
            } catch (e: Exception) {
                Log.e(TAG, "关闭socket失败", e)
            }
        }
    }

    private fun handleUdpPacket(packet: Packet) {
        var socket: DatagramSocket? = null
        try {
            socket = DatagramSocket()
            protect(socket) // 防止 VPN 循环
            
            // 对 DNS 查询特殊处理
            if (packet.destinationPort == 53) {
                handleDnsQuery(socket, packet)
                return
            }
            
            // 非 DNS 的 UDP 包处理
            val datagramPacket = DatagramPacket(
                packet.data,
                packet.data.size,
                InetAddress.getByName(packet.destinationAddress),
                packet.destinationPort
            )
            socket.send(datagramPacket)

            // 接收响应
            val buffer = ByteArray(16384)
            val responsePacket = DatagramPacket(buffer, buffer.size)
            socket.soTimeout = 1000  // 1秒超时
            socket.receive(responsePacket)
            
            if (responsePacket.length > 0) {
                packetProcessor.writePacket(buffer.copyOf(responsePacket.length))
            }
        } catch (e: Exception) {
            Log.e(TAG, "UDP包转发失败: ${e.message}")
        } finally {
            socket?.close()
        }
    }

    private fun handleDnsQuery(socket: DatagramSocket, packet: Packet) {
        try {
            // 设置更短的超时时间
            socket.soTimeout = 1000  // 减少到1秒超时

            // 使用本地系统的 DNS 解析器
            val systemDns = getSystemDns()
            Log.d(TAG, "使用系统 DNS 服务器: $systemDns")

            try {
                val dnsQuery = DatagramPacket(
                    packet.data,
                    packet.data.size,
                    InetAddress.getByName(systemDns),
                    53
                )
                
                socket.send(dnsQuery)
                
                val buffer = ByteArray(4096)
                val response = DatagramPacket(buffer, buffer.size)
                
                socket.receive(response)
                
                if (response.length > 0) {
                    val responseData = buffer.copyOf(response.length)
                    packetProcessor.writePacket(responseData)
                    Log.i(TAG, "DNS查询成功 (系统DNS): ${response.length} bytes")
                    return
                }
            } catch (e: Exception) {
                Log.w(TAG, "系统 DNS 查询失败，尝试备用服务器", e)
            }

            // 如果系统 DNS 失败，尝试备用服务器
            val backupDnsServers = listOf(
                "119.29.29.29",     // 腾讯 DNS
                "223.6.6.6",        // 阿里备用 DNS
                "180.76.76.76",     // 百度 DNS
                "114.114.114.114"   // 114 DNS
            )

            for (dnsServer in backupDnsServers) {
                try {
                    val dnsQuery = DatagramPacket(
                        packet.data,
                        packet.data.size,
                        InetAddress.getByName(dnsServer),
                        53
                    )
                    
                    socket.send(dnsQuery)
                    
                    val buffer = ByteArray(4096)
                    val response = DatagramPacket(buffer, buffer.size)
                    
                    socket.receive(response)
                    
                    if (response.length > 0) {
                        val responseData = buffer.copyOf(response.length)
                        packetProcessor.writePacket(responseData)
                        Log.i(TAG, "DNS查询成功 ($dnsServer): ${response.length} bytes")
                        return
                    }
                } catch (e: Exception) {
                    Log.w(TAG, "DNS服务器 $dnsServer 查询失败", e)
                    continue
                }
            }
            
            Log.e(TAG, "所有 DNS 服务器都查询失败")
            
        } catch (e: Exception) {
            Log.e(TAG, "DNS查询处理失败", e)
        }
    }

    private fun getSystemDns(): String {
        try {
            // 尝试从系统属性获取 DNS
            val process = Runtime.getRuntime().exec("getprop net.dns1")
            val dns = process.inputStream.bufferedReader().readLine()
            if (!dns.isNullOrBlank()) {
                return dns
            }
        } catch (e: Exception) {
            Log.w(TAG, "获取系统 DNS 失败", e)
        }
        
        // 如果无法获取系统 DNS，返回默认值
        return "119.29.29.29"  // 使用腾讯 DNS 作为默认值
    }

    private fun startForwardingThread() {
        Thread {
            forwardPackets()
        }.start()
    }
} 